<!-- DynamicForm.vue -->
<template>
  <el-form
    ref="formRef"
    :model="formModel"
    :rules="formRules"
    label-width="100px"
  >
    <template v-for="item in schema" :key="item.field">
      <!-- 输入框 -->
      <el-form-item
        :label="item.label"
        :prop="item.field"
        v-if="item.type === 'input'"
      >
        <el-input
          v-model="formModel[item.field]"
          :type="item.inputType || 'text'"
          :placeholder="item.placeholder"
          :style="item.style"
        />
      </el-form-item>

      <!-- 单选框 -->
      <el-form-item
        :label="item.label"
        :prop="item.field"
        v-if="item.type === 'radio'"
      >
        <el-radio-group v-model="formModel[item.field]">
          <el-radio
            v-for="opt in item.options"
            :key="opt.value"
            :label="opt.value"
            >{{ opt.label }}</el-radio
          >
        </el-radio-group>
      </el-form-item>

      <!-- 多选框 -->
      <el-form-item
        :label="item.label"
        :prop="item.field"
        v-if="item.type === 'checkbox'"
      >
        <el-checkbox-group v-model="formModel[item.field]">
          <el-checkbox
            v-for="opt in item.options"
            :key="opt.value"
            :label="opt.value"
            >{{ opt.label }}</el-checkbox
          >
        </el-checkbox-group>
      </el-form-item>

      <!-- 下拉框 -->
      <el-form-item
        :label="item.label"
        :prop="item.field"
        v-if="item.type === 'select'"
      >
        <el-select
          v-model="formModel[item.field]"
          :placeholder="item.placeholder"
        >
          <el-option
            v-for="opt in item.options"
            :key="opt.value"
            :label="opt.label"
            :value="opt.value"
          />
        </el-select>
      </el-form-item>

      <!-- 日期选择 -->
      <el-form-item
        :label="item.label"
        :prop="item.field"
        v-if="item.type === 'date'"
      >
        <el-date-picker
          v-model="formModel[item.field]"
          type="date"
          value-format="YYYY-MM-DD"
          :placeholder="item.placeholder"
        />
      </el-form-item>

      <!-- 上传组件 -->
      <el-form-item
        :label="item.label"
        :prop="item.field"
        v-if="item.type === 'upload'"
      >
        <el-upload
          v-model:file-list="formModel[item.field]"
          :action="item.action"
          :limit="item.limit || 5"
          list-type="picture-card"
        >
          <el-icon><Plus /></el-icon>
        </el-upload>
      </el-form-item>

      <!-- 文本展示 -->
      <el-form-item :label="item.label" v-if="item.type === 'text'">
        <span>{{ formModel[item.field] || item.text }}</span>
      </el-form-item>

      <!-- 自定义插槽 -->
      <el-form-item :label="item.label" v-if="item.type === 'slot'">
        <slot :name="item.slotName" :model="formModel" :field="item.field" />
      </el-form-item>
    </template>

    <el-form-item>
      <el-button type="primary" @click="submitForm">提交</el-button>
      <el-button @click="resetForm">重置</el-button>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import { ref, reactive, watch } from "vue";
import type { FormInstance, FormRules } from "element-plus";
import { Plus } from "@element-plus/icons-vue";

interface SchemaItem {
  field: string;
  label: string;
  type: string;
  placeholder?: string;
  inputType?: string;
  options?: { label: string; value: string }[];
  rules?: any[];
  text?: string;
  style?: Record<string, string>;
  action?: string;
  limit?: number;
  slotName?: string;
}

const props = defineProps<{
  schema: SchemaItem[];
  modelValue?: Record<string, any>;
}>();

const emit = defineEmits(["update:modelValue", "submit"]);

const formRef = ref<FormInstance>();
const formModel = reactive<Record<string, any>>({});
const formRules = reactive<FormRules>({});

// 初始化表单
props.schema.forEach((item) => {
  if (item.type === "checkbox") {
    formModel[item.field] = props.modelValue?.[item.field] ?? [];
  } else if (item.type === "upload") {
    formModel[item.field] = props.modelValue?.[item.field] ?? [];
  } else {
    formModel[item.field] = props.modelValue?.[item.field] ?? "";
  }

  if (item.rules) {
    formRules[item.field] = item.rules;
  }
});

// 双向绑定
watch(
  formModel,
  (val) => {
    emit("update:modelValue", val);
  },
  { deep: true }
);

const submitForm = () => {
  formRef.value?.validate((valid) => {
    if (valid) {
      emit("submit", { ...formModel });
    }
  });
};

const resetForm = () => {
  formRef.value?.resetFields();
};
</script>
